/************************************
*  Copyright (C) 2010 Julien MOTTIN.
*  Contact: julien.mottin@gueydan.eu
*
*  This file is part of Gueydan.
*
*  Gueydan is free software: you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation, either version 3 of the License, or
*  (at your option) any later version.
*
*  Gueydan is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU General Public License for more details.
*
*  You should have received a copy of the GNU General Public License
*  along with Gueydan.  If not, see <http://www.gnu.org/licenses/>.
*
*************************************/
// Local
#include "hop.h"
#include "xmldico.h"
#include "beerxmlhandler.h"

// QtCore
#include <QtGlobal>

// QtXml
#include <QDomNode>
#include <QDomElement>
#include <QDomDocument>
#include <QDomNodeList>
#include <QDomText>

Hop::Hop(const QString &iName,
         const int iVersion,
         const float iAlpha,
         const Weight &iAmount,
         HopUse iUse,
         const Duration &iTime)
:BeerXMLObject(iName,iVersion)
,_Alpha(iAlpha)
,_Amount(iAmount)
,_Use(iUse)
,_Time(iTime)
,_Notes()
,_Type(HTUnset)
,_Form(HFUnset)
,_Beta(0.0)
,_HSI(0.0)
,_Origin()
,_Substitutes()
,_Humulene(0.0)
,_Caryophyllene(0.0)
,_Cohumulone(0.0)
,_Myrcene(0.0)
{
}

Hop::Hop()
:BeerXMLObject()
,_Alpha(0.0)
,_Amount(0.0)
,_Use(HUBoil)
,_Time(0.0)
,_Notes()
,_Type(HTUnset)
,_Form(HFUnset)
,_Beta(0.0)
,_HSI(0.0)
,_Origin()
,_Substitutes()
,_Humulene(0.0)
,_Caryophyllene(0.0)
,_Cohumulone(0.0)
,_Myrcene(0.0)
{
}

Hop::~Hop()
{
}

bool Hop::operator==(const Hop &iOther) const
{
    return ((*this).BeerXMLObject::operator==(iOther) &&
    _Alpha == iOther._Alpha &&
    _Amount == iOther._Amount &&
    _Use == iOther._Use &&
    _Time == iOther._Time &&
    _Notes == iOther._Notes &&
    _Type == iOther._Type &&
    _Form == iOther._Form &&
    _Beta == iOther._Beta &&
    _HSI == iOther._HSI &&
    _Origin == iOther._Origin &&
    _Substitutes == iOther._Substitutes &&
    _Humulene == iOther._Humulene &&
    _Caryophyllene == iOther._Caryophyllene &&
    _Cohumulone == iOther._Cohumulone &&
    _Myrcene == iOther._Myrcene);
}

bool Hop::operator!=(const Hop &iOther) const
{
    return (!((*this)==iOther));
}

bool Hop::operator==(const BeerXMLObject &iOther) const
{
    bool res = false;
    BeerXMLHandler hObj(&iOther);
    Hop *pHop = (Hop*)hObj;
    if (pHop)
    {
        res = (*this)==(*pHop);
    }
    return res;
}

bool Hop::operator!=(const BeerXMLObject &iOther) const
{
    return (!((*this)==iOther));
}

int Hop::CreateFromXMLNode(const QDomNode &iNode)
{
    int oRC = 1;
    if (!iNode.isNull())
    {
        QDomElement HopElement;

        // Case Document : check if doc has only one Hop element
        if (iNode.isDocument())
        {
            QDomDocument HopDoc = iNode.toDocument();
            QDomNodeList HopList = HopDoc.elementsByTagName(HOP);
            if (HopList.length()==1)
                HopElement = HopList.item(0).toElement();
        }
        // Default : cast to element
        else
            HopElement = iNode.toElement();

        // Check element consistency
        if (!HopElement.isNull() && HOP==HopElement.tagName())
        {
            // Check existence of mandatory elements
            bool HopName = false;
            bool HopVersion = false;
            bool HopAlpha = false;
            bool HopAmount = false;
            bool HopUse = false;
            bool HopTime = false;
            QDomNode node = HopElement.firstChild();
            while (!node.isNull())
            {
                if (node.isElement())
                {
                    QDomElement elem = node.toElement();
                    QString name = elem.tagName();
                    QString text = elem.text();
                    if (name==HOP_NAME)
                    {
                        _Name = text;
                        HopName = true;
                    }
                    else if (name==HOP_VERSION)
                    {
                        bool ok = false;
                        int v = text.toInt(&ok);
                        if (ok)
                        {
                            _Version = v;
                            HopVersion = true;
                        }
                    }
                    else if (name==HOP_ALPHA)
                    {
                        bool ok = false;
                        float v = text.toFloat(&ok);
                        if (ok)
                        {
                            _Alpha = v;
                            HopAlpha = true;
                        }

                    }
                    else if (name==HOP_AMOUNT)
                    {
                        bool ok = false;
                        Weight tmpAmount;
                        tmpAmount.FromString(text,&ok);
                        if (ok)
                        {
                            _Amount = tmpAmount;
                            HopAmount = true;
                        }
                    }
                    else if (name==HOP_USE)
                    {
                        QString use = text.toLower();
                        HopUse = true;
                        if (use==HOP_USE_BOIL.toLower())
                            _Use = HUBoil;
                        else if (use==HOP_USE_DRYHOP.toLower())
                            _Use = HUDryHop;
                        else if (use==HOP_USE_MASH.toLower())
                            _Use = HUMash;
                        else if (use==HOP_USE_FIRSTWORT.toLower())
                            _Use = HUFirstWort;
                        else if (use==HOP_USE_AROMA.toLower())
                            _Use = HUAroma;
                        else
                        {
                            // Unknown use!
                            HopUse = false;
                            break;
                        }
                    }
                    else if (name==HOP_TIME)
                    {
                        bool ok = false;
                        Duration tmpDuration;
                        tmpDuration.FromString(text,&ok);
                        if (ok)
                        {
                            _Time = tmpDuration;
                            HopTime = true;
                        }
                    }
                    else if (name==HOP_NOTES)
                    {
                        _Notes = text;
                    }
                    else if (name==HOP_TYPE)
                    {
                        QString type = text.toLower();
                        if (type==HOP_TYPE_BITTERING.toLower())
                            _Type = HTBittering;
                        else if (type==HOP_TYPE_AROMA.toLower())
                            _Type = HTAroma;
                        else if (type==HOP_TYPE_BOTH.toLower())
                            _Type = HTBoth;
                    }
                    else if (name==HOP_FORM)
                    {
                        QString form = text.toLower();
                        if (form==HOP_FORM_PELLET.toLower())
                            _Form = HFPellet;
                        else if (form==HOP_FORM_PLUG.toLower())
                            _Form = HFPlug;
                        else if (form==HOP_FORM_LEAF.toLower())
                            _Form = HFLeaf;
                    }
                    else if (name==HOP_BETA)
                    {
                        bool ok = false;
                        float v = text.toFloat(&ok);
                        if (ok)
                            _Beta = v;
                    }
                    else if (name==HOP_HSI)
                    {
                        bool ok = false;
                        float v = text.toFloat(&ok);
                        if (ok)
                            _HSI = v;
                    }
                    else if (name==HOP_ORIGIN)
                    {
                        _Origin = text;
                    }
                    else if (name==HOP_SUBSTITUTES)
                    {
                        _Substitutes = text;
                    }
                    else if (name==HOP_HUMULENE)
                    {
                        bool ok = false;
                        float v = text.toFloat(&ok);
                        if (ok)
                            _Humulene = v;
                    }
                    else if (name==HOP_CARYOPHYLLENE)
                    {
                        bool ok = false;
                        float v = text.toFloat(&ok);
                        if (ok)
                            _Caryophyllene = v;
                    }
                    else if (name==HOP_COHUMULONE)
                    {
                        bool ok = false;
                        float v = text.toFloat(&ok);
                        if (ok)
                            _Cohumulone = v;
                    }
                    else if (name==HOP_MYRCENE)
                    {
                        bool ok = false;
                        float v = text.toFloat(&ok);
                        if (ok)
                            _Myrcene = v;
                    }
                }

                // Iterate
                node = node.nextSibling();
            }

            // Check & update output
            if (HopName && HopVersion && HopAlpha && HopAmount && HopUse && HopTime)
            {
                // Success
                oRC = 0;
            }
        }
    }

    return oRC;
}

int Hop::ToXMLNode(QDomNode &iParentNode) const
{
    int oRC = 1;

    // First, create valid element node
    QDomDocument doc = iParentNode.ownerDocument();
    QDomElement HopNode = doc.createElement(HOP);
    if (!HopNode.isNull())
    {
        if (!_Name.isEmpty() && _Version>0 && _Alpha>=0)
        {
            // Name
            QDomElement NameNode = doc.createElement(HOP_NAME);
            Q_ASSERT(!NameNode.isNull());
            QDomText NameText = doc.createTextNode(_Name);
            Q_ASSERT(!NameText.isNull());
            NameNode.appendChild(NameText);
            HopNode.appendChild(NameNode);

            // Version
            QDomElement VersionNode = doc.createElement(HOP_VERSION);
            Q_ASSERT(!VersionNode.isNull());
            QDomText VersionText = doc.createTextNode(QString::number(_Version));
            Q_ASSERT(!VersionText.isNull());
            VersionNode.appendChild(VersionText);
            HopNode.appendChild(VersionNode);

            // Alpha
            QDomElement AlphaNode = doc.createElement(HOP_ALPHA);
            Q_ASSERT(!AlphaNode.isNull());
            QDomText AlphaText = doc.createTextNode(QString::number(_Alpha));
            Q_ASSERT(!AlphaText.isNull());
            AlphaNode.appendChild(AlphaText);
            HopNode.appendChild(AlphaNode);

            // Amount
            QDomElement AmountNode = doc.createElement(HOP_AMOUNT);
            Q_ASSERT(!AmountNode.isNull());
            QDomText AmountText = doc.createTextNode(QString::number(_Amount.Value(Kilogram)));
            Q_ASSERT(!AmountText.isNull());
            AmountNode.appendChild(AmountText);
            HopNode.appendChild(AmountNode);

            // Use
            QDomElement UseNode = doc.createElement(HOP_USE);
            Q_ASSERT(!UseNode.isNull());
            QString strText;
            switch (_Use)
            {
            case HUBoil:
                strText = HOP_USE_BOIL;
                break;
            case HUDryHop:
                strText = HOP_USE_DRYHOP;
                break;
            case HUMash:
                strText = HOP_USE_MASH;
                break;
            case HUFirstWort:
                strText = HOP_USE_FIRSTWORT;
                break;
            case HUAroma:
                strText = HOP_USE_AROMA;
                break;
            }
            QDomText UseText = doc.createTextNode(strText);
            Q_ASSERT(!UseText.isNull());
            UseNode.appendChild(UseText);
            HopNode.appendChild(UseNode);

            // Time
            QDomElement TimeNode = doc.createElement(HOP_TIME);
            Q_ASSERT(!TimeNode.isNull());
            QDomText TimeText = doc.createTextNode(QString::number(_Time.Value(Minute)));
            Q_ASSERT(!TimeText.isNull());
            TimeNode.appendChild(TimeText);
            HopNode.appendChild(TimeNode);

            // Notes
            if (!_Notes.isEmpty())
            {
                QDomElement NotesNode = doc.createElement(HOP_NOTES);
                Q_ASSERT(!NotesNode.isNull());
                QDomText NoteText = doc.createTextNode(_Notes);
                Q_ASSERT(!NoteText.isNull());
                NotesNode.appendChild(NoteText);
                HopNode.appendChild(NotesNode);
            }

            // Type
            if (_Type!=HTUnset)
            {
                QString strType;
                switch (_Type)
                {
                case HTBittering:
                    strType = HOP_TYPE_BITTERING;
                    break;
                case HTAroma:
                    strType = HOP_TYPE_AROMA;
                    break;
                case HTBoth:
                    strType = HOP_TYPE_BOTH;
                    break;
                default:
                    strType = "";
                }

                QDomElement TypeNode = doc.createElement(HOP_TYPE);
                Q_ASSERT(!TypeNode.isNull());
                QDomText TypeText = doc.createTextNode(strType);
                Q_ASSERT(!TypeText.isNull());
                TypeNode.appendChild(TypeText);
                HopNode.appendChild(TypeNode);
            }

            // Form
            if (_Form!=HFUnset)
            {
                QString strForm;
                switch (_Form)
                {
                case HFPellet:
                    strForm = HOP_FORM_PELLET;
                    break;
                case HFPlug:
                    strForm = HOP_FORM_PLUG;
                    break;
                case HFLeaf:
                    strForm = HOP_FORM_LEAF;
                    break;
                default:
                    strForm = "";
                }

                QDomElement FormNode = doc.createElement(HOP_FORM);
                Q_ASSERT(!FormNode.isNull());
                QDomText FormText = doc.createTextNode(strForm);
                Q_ASSERT(!FormText.isNull());
                FormNode.appendChild(FormText);
                HopNode.appendChild(FormNode);
            }

            // Beta
            if (_Beta>0)
            {                
                QDomElement BetaNode = doc.createElement(HOP_BETA);
                Q_ASSERT(!BetaNode.isNull());
                QDomText BetaText = doc.createTextNode(QString::number(_Beta));
                Q_ASSERT(!BetaText.isNull());
                BetaNode.appendChild(BetaText);
                HopNode.appendChild(BetaNode);
            }

            // HSI
            if (_HSI>0)
            {
                QDomElement Node = doc.createElement(HOP_HSI);
                Q_ASSERT(!Node.isNull());
                QDomText Text = doc.createTextNode(QString::number(_HSI));
                Q_ASSERT(!Text.isNull());
                Node.appendChild(Text);
                HopNode.appendChild(Node);
            }

            // Origin
            if (!_Origin.isEmpty())
            {
                QDomElement Node = doc.createElement(HOP_ORIGIN);
                Q_ASSERT(!Node.isNull());
                QDomText Text = doc.createTextNode(_Origin);
                Q_ASSERT(!Text.isNull());
                Node.appendChild(Text);
                HopNode.appendChild(Node);
            }

            // Substitutes
            if (!_Substitutes.isEmpty())
            {
                QDomElement Node = doc.createElement(HOP_SUBSTITUTES);
                Q_ASSERT(!Node.isNull());
                QDomText Text = doc.createTextNode(_Substitutes);
                Q_ASSERT(!Text.isNull());
                Node.appendChild(Text);
                HopNode.appendChild(Node);
            }

            // Humulene
            if (_Humulene>0)
            {
                QDomElement Node = doc.createElement(HOP_HUMULENE);
                Q_ASSERT(!Node.isNull());
                QDomText Text = doc.createTextNode(QString::number(_Humulene));
                Q_ASSERT(!Text.isNull());
                Node.appendChild(Text);
                HopNode.appendChild(Node);
            }

            // Caryophyllene
            if (_Caryophyllene>0)
            {
                QDomElement Node = doc.createElement(HOP_CARYOPHYLLENE);
                Q_ASSERT(!Node.isNull());
                QDomText Text = doc.createTextNode(QString::number(_Caryophyllene));
                Q_ASSERT(!Text.isNull());
                Node.appendChild(Text);
                HopNode.appendChild(Node);
            }

            // Cohumulone
            if (_Cohumulone>0)
            {
                QDomElement Node = doc.createElement(HOP_COHUMULONE);
                Q_ASSERT(!Node.isNull());
                QDomText Text = doc.createTextNode(QString::number(_Cohumulone));
                Q_ASSERT(!Text.isNull());
                Node.appendChild(Text);
                HopNode.appendChild(Node);
            }

            // Myrcene
            if (_Myrcene>0)
            {
                QDomElement Node = doc.createElement(HOP_MYRCENE);
                Q_ASSERT(!Node.isNull());
                QDomText Text = doc.createTextNode(QString::number(_Myrcene));
                Q_ASSERT(!Text.isNull());
                Node.appendChild(Text);
                HopNode.appendChild(Node);
            }

            // Update output
            QDomNode zeNode = iParentNode.appendChild(HopNode);
            if (!zeNode.isNull())
                oRC = 0;
        }
    }

    return oRC;
}
